package demoMod.stsconsole.commands;

import demoMod.stsconsole.ConsoleEntry;
import demoMod.stsconsole.cards.AbstractCard;
import demoMod.stsconsole.core.AbstractCreature;
import demoMod.stsconsole.core.CombatManager;
import demoMod.stsconsole.dungeons.AbstractDungeon;
import demoMod.stsconsole.enums.ErrType;
import demoMod.stsconsole.helpers.LocalizedStrings;
import demoMod.stsconsole.helpers.PromptHelper;
import demoMod.stsconsole.interfaces.CardMoveToDiscardPileSubscriber;
import demoMod.stsconsole.interfaces.ExhaustCardSubscriber;
import demoMod.stsconsole.interfaces.PotionUseSubscriber;
import demoMod.stsconsole.interfaces.UseCardSubscriber;
import demoMod.stsconsole.monsters.AbstractMonster;
import demoMod.stsconsole.potions.AbstractPotion;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Use extends AbstractCommand {
    @Override
    public void execute(String[] args, Scanner sc) {
        if (args.length == 0) {
            this.errMsg(ErrType.WRONG_ARGUMENT);
            return;
        }
        List<AbstractMonster> removeMonsterLater = new ArrayList<>();
        for (AbstractCreature creature : AbstractDungeon.currDungeon.currMapNode.room.monsters.monsters) {
            if (creature instanceof AbstractMonster && creature.isDeadOrEscaped()) {
                AbstractMonster monster = (AbstractMonster) creature;
                removeMonsterLater.add(monster);
            }
        }
        AbstractDungeon.currDungeon.currMapNode.room.monsters.monsters.removeAll(removeMonsterLater);
        switch (args[0]) {
            case "card":
                if (!PromptHelper.getPrompt().contains("Combat")) {
                    this.errMsg(ErrType.WRONG_PROMPT);
                    return;
                }
                if (args.length == 1) {
                    this.errMsg(ErrType.WRONG_ARGUMENT);
                    return;
                } else {
                    if (AbstractDungeon.currDungeon.currMapNode.room.combatManager.turnsOwner != CombatManager.TurnsOwner.PLAYER) { //玩家只能在自己的回合出牌
                        AbstractDungeon.player.talk(AbstractDungeon.player.commonStrings.get(1));
                        return;
                    }
                    try {
                        int index = Integer.parseInt(args[1]);
                        if (index < 0 || index >= AbstractDungeon.player.hand.size()) {
                            this.errMsg(ErrType.WRONG_ARGUMENT);
                            return;
                        }
                        AbstractCard card = AbstractDungeon.player.hand.get(index);
                        AbstractCreature target = null;
                        if (card.target == AbstractCard.CardTarget.ENEMY) {
                            List<String> cmdStrings = LocalizedStrings.getCommandStrings("Use");
                            System.out.println(cmdStrings.get(0));
                            index = 0;
                            for (AbstractCreature creature : AbstractDungeon.currDungeon.currMapNode.room.monsters.monsters) {
                                if (!creature.isDeadOrEscaped()) {
                                    System.out.println(index + "\t" + creature.name);
                                }
                                index++;
                            }
                            index = Integer.parseInt(sc.nextLine());
                            if (index < 0 || index >= AbstractDungeon.currDungeon.currMapNode.room.monsters.monsters.size() || AbstractDungeon.currDungeon.currMapNode.room.monsters.monsters.get(index).isDeadOrEscaped()) {
                                this.errMsg(ErrType.WRONG_ARGUMENT);
                                return;
                            }
                            target = AbstractDungeon.currDungeon.currMapNode.room.monsters.monsters.get(index);
                        }
                        card.calculateCardDamage(target);
                        System.out.println(card.name);
                        List<String> cmdStrings = LocalizedStrings.getCommandStrings("Smith");
                        System.out.print(cmdStrings.get(3));
                        if (card.cost == -1) {
                            System.out.println("X");
                        } else if (!card.canUse) {
                            System.out.println("-");
                        } else {
                            System.out.println(card.cost);
                        }
                        System.out.println(card.getUpdatedDescriptions(target));
                        cmdStrings = LocalizedStrings.getCommandStrings("Use");
                        if (target != null) {
                            System.out.printf(cmdStrings.get(1), target.name);
                        } else {
                            System.out.print(cmdStrings.get(2));
                        }
                        if ("y".equalsIgnoreCase(sc.nextLine())) {
                            cmdStrings = LocalizedStrings.getCharacterStrings("AbstractPlayer");
                            ConsoleEntry.triggerSubscribers(UseCardSubscriber.class, "preUseCard", new Class[]{AbstractCard.class}, new Object[]{card});
                            if (card.canUse) {
                                if (card.cost <= AbstractDungeon.player.currEnergy) {
                                    if (card.use(AbstractDungeon.player, target)) {
                                        if (card.type == AbstractCard.CardType.POWER) {
                                            card.purge = true;
                                        }
                                        ConsoleEntry.triggerSubscribers(UseCardSubscriber.class, "postUseCard", new Class[]{AbstractCard.class}, new Object[]{card});
                                        if (!card.freeToPlayOnce) {
                                            if (card.cost == -1) {
                                                AbstractDungeon.player.currEnergy = 0;
                                            } else {
                                                AbstractDungeon.player.currEnergy -= Math.max(card.cost, 0);
                                            }
                                        }

                                        card.freeToPlayOnce = false;
                                        if (card.exhaust) {
                                            ConsoleEntry.triggerSubscribers(ExhaustCardSubscriber.class, "onExhaustCard", new Class[]{AbstractCard.class}, new Object[]{card});
                                        }
                                        if (!card.returnToHand || card.exhaust || card.purge) AbstractDungeon.player.hand.remove(card);
                                        if (card.exhaust && !card.purge) {
                                            if (!AbstractDungeon.player.exhaustPile.contains(card)) AbstractDungeon.player.exhaustPile.add(card);
                                        } else {
                                            if (card.purge) {
                                                card.onRemove();
                                            } else if (!card.returnToHand) {
                                                AbstractDungeon.player.discardPile.add(card);
                                                ConsoleEntry.triggerSubscribers(CardMoveToDiscardPileSubscriber.class, "postCardMoveToDiscardPile", new Class[]{AbstractCard.class}, new Object[]{card});
                                            }
                                        }
                                    } else {
                                        AbstractDungeon.player.talk(cmdStrings.get(3));
                                    }
                                } else {
                                    AbstractDungeon.player.talk(cmdStrings.get(2));
                                }
                            } else {
                                AbstractDungeon.player.talk(cmdStrings.get(3));
                            }
                        }
                    } catch (NumberFormatException e) {
                        this.errMsg(ErrType.WRONG_ARGUMENT);
                    }
                }
                break;
            case "potion":
                if (args.length == 1) {
                    this.errMsg(ErrType.WRONG_ARGUMENT);
                    return;
                }
                try {
                    int index = Integer.parseInt(args[1]);
                    if (index < 0 || index >= AbstractDungeon.player.getPotions().size()) {
                        this.errMsg(ErrType.WRONG_ARGUMENT);
                        return;
                    }
                    AbstractPotion potion = AbstractDungeon.player.getPotions().get(index);
                    if (!potion.canUse()) {
                        System.out.println(LocalizedStrings.getCommandStrings("Use").get(5));
                        return;
                    }
                    AbstractCreature target = null;
                    if (potion.target == AbstractPotion.Target.ENEMY) {
                        List<String> cmdStrings = LocalizedStrings.getCommandStrings("Use");
                        System.out.println(cmdStrings.get(0));
                        index = 0;
                        for (AbstractCreature creature : AbstractDungeon.currDungeon.currMapNode.room.monsters.monsters) {
                            System.out.println(index + "\t" + creature.name);
                            index++;
                        }
                        index = Integer.parseInt(sc.nextLine());
                        if (index < 0 || index >= AbstractDungeon.currDungeon.currMapNode.room.monsters.monsters.size()) {
                            this.errMsg(ErrType.WRONG_ARGUMENT);
                            return;
                        }
                        target = AbstractDungeon.currDungeon.currMapNode.room.monsters.monsters.get(index);
                    }
                    System.out.println(potion.name);
                    System.out.println(potion.getUpdatedDescription());
                    List<String> cmdStrings = LocalizedStrings.getCommandStrings("Use");
                    if (target != null) {
                        System.out.printf(cmdStrings.get(3), target.name);
                    } else {
                        System.out.print(cmdStrings.get(4));
                    }
                    if ("y".equalsIgnoreCase(sc.nextLine())) {
                        AbstractDungeon.player.destroyPotion(potion);
                        potion.use(target);
                        ConsoleEntry.triggerSubscribers(PotionUseSubscriber.class, "postPotionUse", new Class[]{AbstractPotion.class}, new Object[]{potion});
                    }
                } catch (NumberFormatException e) {
                    this.errMsg(ErrType.WRONG_ARGUMENT);
                }
        }
    }

    @Override
    public boolean requiredPrompt(String currentPrompt) {
        return currentPrompt.contains("Dungeon");
    }
}
